chdkfandomcom-20200222-history
Canon Basic/Scripts/Loader
Canon basic binary loader This script loads and boots the specified ARM binary. The binary should be unencoded, and loadable at 0x1900 After a CHDK build, a suitable binary can be found at loader//main.bin. Tested on a540 (vxworks) and D10 (dryos) Free memory must be > the size of the binary. This may be a problem on some cameras, especially if CHDK is already running and there are images on the camera. original discussion thread with background information http://chdk.setepontos.com/index.php?topic=5648.0 ' bootbin is the image to load. It must be an unencoded arm binary DIM bootbin = "A/MAIN.BIN" DIM lcdmsg=0 DIM msgstr=0 PRIVATE SUB RegisterProcs() ' Newest cams (Dryos rel 43 and later) only have System.Create() ' on older dryos cams SystemEventInit is an alias for System.Create() ' ExecuteEventProcedure does is not registered by default on vx, ' but calling an unregistered is not fatal if System.Create() = -1 then SystemEventInit() end if if ExecuteEventProcedure("UI_RegistDebugEventProc") = -1 then ExecuteEventProcedure("UI.CreatePublic") end if ExecuteEventProcedure("DispDev_EnableEventProc") END SUB PRIVATE SUB InitMsg() lcdmsg = ExecuteEventProcedure("LCDMsg_Create") ' not default black if lcdmsg >= 0 then LCDMsg_ChangeColor(lcdmsg,2) LCDMsg_SetStr(lcdmsg,"started") end if msgstr = AllocateMemory(80) ' truncate log msgfile = Fopen_Fut("A/CBLOADER.LOG","w") if msgfile <> 0 then Fclose_Fut(msgfile) end if END SUB PRIVATE SUB PutMsg(msg) if lcdmsg >= 0 then LCDMsg_SetStr(lcdmsg,msg) end if msgfile = Fopen_Fut("A/CBLOADER.LOG","a") if msgfile <> 0 then Fwrite_Fut(msg,strlen(msg),1,msgfile) Fwrite_Fut("\n",1,1,msgfile) Fclose_Fut(msgfile) end if END SUB ' put some ARM code in a buffer ' this should be in uncacheable memory, but function is not available on older cams ' in practice, loading the main image should ensure all this is flushed out ' pad binary to > 4k or so if needed ' can't use strings with \xHH because older cams don't support ' parameters: ' R0 source address ' R1 size ' never returns, saves nothing on the stack PRIVATE SUB MakeLoader() buf = AllocateMemory(76) p = buf *p = 0xee113f10 ' MRC p15, 0, R3, c1, c0, 0 p = p + 4 *p = 0xe3c33a01 ' BIC R3, R3, #0x1000 // icache bit p = p + 4 *p = 0xe3c33004 ' BIC R3, R3, #0x4 // dcache bit p = p + 4 *p = 0xee013f10 ' MCR p15, 0, R3, c1, c0, 0 p = p + 4 *p = 0xe3a03000 ' MOV R3, #0 p = p + 4 *p = 0xee073f9a ' MCR p15, 0, R3,c7,c10, 4 // drain write buffer p = p + 4 *p = 0xee073f15 ' MCR p15, 0, R3,c7,c5 // flush icache p = p + 4 *p = 0xee073f16 ' MCR p15, 0, R3,c7,c6 // flush dcache p = p + 4 *p = 0xe10f4000 ' MRS R4, CPSR p = p + 4 *p = 0xe3844080 ' ORR R4, R4, #0x80 p = p + 4 *p = 0xe12ff004 ' MSR CPSR_cxsf, R4 // disable IRQs p = p + 4 *p = 0xee195f11 ' MRC p15, 0, R5, c9, c1, 0 // read data TCM config p = p + 4 *p = 0xe1a05625 ' MOV R5, R5, LSR#12 // clear the lower 12 bits p = p + 4 *p = 0xe7935605 ' LDR R5, R5, LSL#12 // R3 is still 0 p = p + 4 *p = 0xe1a02001 ' MOV R2, R1 p = p + 4 *p = 0xe1a01000 ' MOV R1, R0 p = p + 4 *p = 0xe3a00c19 ' MOV R0, #0x1900 p = p + 4 *p = 0xe3a03c19 ' MOV R3, #0x1900 p = p + 4 *p = 0xe12fff35 ' BLX R5 MakeLoader = buf END SUB PRIVATE SUB LoadNBoot() loader = MakeLoader() fd = Open(bootbin,0) IF fd = -1 THEN PutMsg("bootbin size fail") EXIT SUB END IF imgsize = Lseek(fd,0,2) Close(fd) imgbuf = AllocateMemory(imgsize) IF imgbuf = 0 THEN sprintf(msgstr,"alloc %d fail",imgsize) PutMsg(msgstr) EXIT SUB END IF fd = Fopen_Fut(bootbin,"r") IF fd = 0 THEN sprintf(msgstr,"open %s fail",bootbin) PutMsg(msgstr) EXIT SUB END IF rcnt = Fread_Fut(imgbuf,1,imgsize,fd) Fclose_Fut(fd) IF rcnt <> imgsize THEN sprintf(msgstr,"read %d fail",imgsize) PutMsg(msgstr) FreeMemory(imgbuf) EXIT SUB END IF sprintf(msgstr,"%s %d",bootbin,imgsize) PutMsg(msgstr) Wait(500) ' register the start of loader as a function ExportToEventProcedure("loader_func",loader) DispCon_TurnOffDisplay() ' if starting is very slow, watchdog can hit before loading is complete ' but may stay on indefinitely if we crash StopWDT() loader_func(imgbuf,imgsize) ' if loader_func could return, we could try to restore 'StartWDT() 'DispCon_TurnOnDisplay() END SUB PRIVATE SUB Initialize() RegisterProcs() InitMsg() LoadNBoot() END SUB Category:CanonBasic Category:Development Category:Scripts